package jmine.tec.utils.annotation.visitor;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.List;

/**
 * Classe para ler as anotacoes de outra, no estilo visitor. Devolve um conjunto de R que representam o retorno de cada parse.
 * 
 * @author takeshi
 * @param <R> o tipo do resultado
 */
public interface ClassAnnotationReader<R> {

    /**
     * adiciona um visitor
     * 
     * @param visitor o visitor
     */
    void addClassAnnotationVisitor(ClassAnnotationVisitor<? extends R> visitor);

    /**
     * adiciona um visitor
     * 
     * @param visitor o visitor
     */
    void addMethodAnnotationVisitor(MethodAnnotationVisitor<? extends R> visitor);

    /**
     * adiciona um visitor
     * 
     * @param visitor o visitor
     */
    void addParameterAnnotationVisitor(ParameterAnnotationVisitor<? extends R> visitor);

    /**
     * adiciona um visitor
     * 
     * @param visitor o visitor
     */
    void addFieldAnnotationVisitor(FieldAnnotationVisitor<? extends R> visitor);

    /**
     * Visita todas as anotacoes desta classe que estejam disponiveis via reflection.
     * 
     * @param type o tipo
     * @return {@link List} de R
     */
    List<? extends R> visitAll(Class<?> type);

    /**
     * visita as anotacoes presentes na declaracao da classe passada
     * 
     * @param type o tipo
     * @return {@link List} de R
     */
    List<? extends R> visitClassAnnotations(Class<?> type);

    /**
     * Visita os campos da classe passada
     * 
     * @param type {@link Class}
     * @return {@link List} de R
     */
    List<? extends R> visitFieldsAnnotations(Class<?> type);

    /**
     * Visita as anotacoes do campo passado
     * 
     * @param type {@link Class}
     * @param field {@link Field}
     * @return {@link List} de R
     */
    List<? extends R> visitFieldAnnotations(Class<?> type, Field field);

    /**
     * visita as anotacoes presentes em todos os metodos da classe passada, incluindo construtores e incluindo anotacoes presentes nos
     * parametros dos metodos e construtores
     * 
     * @param type o tipo
     * @return {@link List} de R
     */
    List<? extends R> visitAllMethodsAnnotations(Class<?> type);

    /**
     * Visita as anotacoes presentes na declaracao do metodo
     * 
     * @param method o {@link Method}
     * @param declaringClass a classe que contem o metodo
     * @return {@link List} de R
     */
    List<? extends R> visitMethodAnnotation(Method method, Class<?> declaringClass);

    /**
     * Visita as anotacoes dos parametros do metodo
     * 
     * @param method {@link Method}
     * @param declaringClass a classe que contem o metodo
     * @return {@link List} de R
     */
    List<? extends R> visitMethodParametersAnnotation(Method method, Class<?> declaringClass);

    /**
     * Visita as anotacoes dos construtores dos parametros do metodo
     * 
     * @param ctor Constructor
     * @return {@link List} de R
     */
    List<? extends R> visitConstructorParametersAnnotation(Constructor<?> ctor);

    /**
     * Visita as anotacoes do construtor
     * 
     * @param ctor {@link Constructor}
     * @return {@link List} de R
     */
    List<? extends R> visitConstructorAnnotation(Constructor<?> ctor);

    /**
     * Seleciona os metodos que serao visitados
     * 
     * @param type {@link Class}
     * @return array de {@link Method}
     */
    Collection<? extends Method> selectMethods(Class<?> type);

    /**
     * Seleciona os tipos que serao visitados
     * 
     * @param baseType Class
     * @return Collection de Class
     */
    Collection<? extends Class<?>> selectTypes(Class<?> baseType);

    /**
     * Devolve os campos que serao visitados
     * 
     * @param type {@link Class}
     * @return {@link Field}
     */
    Collection<? extends Field> selectFields(Class<?> type);
}
